mirror of
https://github.com/nefarius/ViGEmBus.git
synced 2025-08-10 00:52:17 +00:00
Compare commits
17 Commits
v1.17.241.
...
v1.17.258.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dbf948fdb | ||
|
|
64ca258915 | ||
|
|
2fe83018c0 | ||
|
|
05b3b74db5 | ||
|
|
5bea1d5b0f | ||
|
|
f9eaad93f2 | ||
|
|
81b6fb3926 | ||
|
|
9f4e557d94 | ||
|
|
80330f6716 | ||
|
|
af18a07443 | ||
|
|
250d6f7937 | ||
|
|
68ab55d56a | ||
|
|
dc39ba970d | ||
|
|
2f636a5da6 | ||
|
|
15a9b2c896 | ||
|
|
5d2dd2a122 | ||
|
|
225c536205 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -357,4 +357,7 @@ MigrationBackup/
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
FodyWeavers.xsd
|
||||
/disk1/ViGEmBus_x64.cab
|
||||
/setup.inf
|
||||
/setup.rpt
|
||||
|
||||
@@ -93,6 +93,8 @@ This list is non-exhaustive, if you'd like to see your project included, contact
|
||||
- [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)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
21
ViGEmBus.ddf
21
ViGEmBus.ddf
@@ -1,21 +0,0 @@
|
||||
.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
|
||||
.Set CabinetNameTemplate=ViGEmBus.cab
|
||||
.Set DestinationDir=ViGEmBus
|
||||
.\artifacts\ViGEmBus.inf
|
||||
.Set DestinationDir=ViGEmBus\x64
|
||||
.\artifacts\x64\ViGEmBus.sys
|
||||
.\artifacts\x64\ViGEmBus.pdb
|
||||
.\artifacts\x64\WdfCoinstaller01009.dll
|
||||
.Set DestinationDir=ViGEmBus\x86
|
||||
.\artifacts\x86\ViGEmBus.sys
|
||||
.\artifacts\x86\ViGEmBus.pdb
|
||||
.\artifacts\x86\WdfCoinstaller01009.dll
|
||||
19
ViGEmBus_x64.ddf
Normal file
19
ViGEmBus_x64.ddf
Normal file
@@ -0,0 +1,19 @@
|
||||
; 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
|
||||
; x64
|
||||
.Set CabinetNameTemplate=ViGEmBus_x64.cab
|
||||
.Set DestinationDir=ViGEmBus_x64
|
||||
LICENSE
|
||||
bin\x64\ViGEmBus.pdb
|
||||
bin\x64\ViGEmBus\ViGEmBus.inf
|
||||
bin\x64\ViGEmBus\ViGEmBus.sys
|
||||
bin\x64\ViGEmBus\WdfCoinstaller01009.dll
|
||||
19
ViGEmBus_x86.ddf
Normal file
19
ViGEmBus_x86.ddf
Normal file
@@ -0,0 +1,19 @@
|
||||
; 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
|
||||
; x86
|
||||
.Set CabinetNameTemplate=ViGEmBus_x86.cab
|
||||
.Set DestinationDir=ViGEmBus_x86
|
||||
LICENSE
|
||||
bin\x86\ViGEmBus.pdb
|
||||
bin\x86\ViGEmBus\ViGEmBus.inf
|
||||
bin\x86\ViGEmBus\ViGEmBus.sys
|
||||
bin\x86\ViGEmBus\WdfCoinstaller01009.dll
|
||||
@@ -14,12 +14,13 @@ before_build:
|
||||
build:
|
||||
project: $(APPVEYOR_BUILD_FOLDER)\$(APPVEYOR_PROJECT_NAME).sln
|
||||
after_build:
|
||||
#- cmd: makecab.exe /f ViGEmBus.ddf
|
||||
- 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'
|
||||
deploy:
|
||||
- provider: Environment
|
||||
name: BUILDBOT
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
// {A77BC4D5-6AF7-4E69-8DC4-6B88A6028CE6}
|
||||
// ReSharper disable once CppMissingIncludeGuard
|
||||
DEFINE_GUID(GUID_VIGEM_INTERFACE_PDO,
|
||||
0xA77BC4D5, 0x6AF7, 0x4E69, 0x8D, 0xC4, 0x6B, 0x88, 0xA6, 0x02, 0x8C, 0xE6);
|
||||
|
||||
// {A8BA2D1F-894F-464A-B0CE-7A0C8FD65DF1}
|
||||
DEFINE_GUID(GUID_DEVCLASS_VIGEM_RAWPDO,
|
||||
0xA8BA2D1F, 0x894F, 0x464A, 0xB0, 0xCE, 0x7A, 0x0C, 0x8F, 0xD6, 0x5D, 0xF1);
|
||||
|
||||
#pragma once
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
//
|
||||
// Describes the current stage a PDO completed
|
||||
//
|
||||
typedef enum _VIGEM_PDO_STAGE
|
||||
{
|
||||
ViGEmPdoCreate,
|
||||
ViGEmPdoPrepareHardware,
|
||||
ViGEmPdoInitFinished
|
||||
|
||||
} VIGEM_PDO_STAGE, *PVIGEM_PDO_STAGE;
|
||||
|
||||
//
|
||||
// PDO stage result callback definition
|
||||
//
|
||||
typedef
|
||||
VOID
|
||||
(*PVIGEM_BUS_PDO_STAGE_RESULT)(
|
||||
_In_ PINTERFACE InterfaceHeader,
|
||||
_In_ VIGEM_PDO_STAGE Stage,
|
||||
_In_ ULONG Serial,
|
||||
_In_ NTSTATUS Status
|
||||
);
|
||||
|
||||
typedef struct _VIGEM_BUS_INTERFACE {
|
||||
//
|
||||
// Standard interface header, must be present
|
||||
//
|
||||
INTERFACE InterfaceHeader;
|
||||
|
||||
//
|
||||
// PDO stage result callback
|
||||
//
|
||||
PVIGEM_BUS_PDO_STAGE_RESULT BusPdoStageResult;
|
||||
|
||||
} VIGEM_BUS_INTERFACE, *PVIGEM_BUS_INTERFACE;
|
||||
|
||||
#define VIGEM_BUS_INTERFACE_VERSION 1
|
||||
|
||||
VOID FORCEINLINE BUS_PDO_REPORT_STAGE_RESULT(
|
||||
VIGEM_BUS_INTERFACE Interface,
|
||||
VIGEM_PDO_STAGE Stage,
|
||||
ULONG Serial,
|
||||
NTSTATUS Status
|
||||
)
|
||||
{
|
||||
(*Interface.BusPdoStageResult)(&Interface.InterfaceHeader, Stage, Serial, Status);
|
||||
}
|
||||
|
||||
EXTERN_C_END
|
||||
216
sys/ByteArray.c
216
sys/ByteArray.c
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "ByteArray.h"
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
ULONG_PTR align_to_page_size(ULONG_PTR val)
|
||||
{
|
||||
return (val + (PAGE_SIZE - 1)) & -PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Forward declarations
|
||||
//
|
||||
|
||||
NTSTATUS IncreaseCapacityByteArray(IN PBYTE_ARRAY Array, IN ULONG NumElements);
|
||||
|
||||
|
||||
//
|
||||
// Implementation
|
||||
//
|
||||
|
||||
NTSTATUS InitByteArray(IN OUT PBYTE_ARRAY Array)
|
||||
{
|
||||
//
|
||||
// Initialize size and default capacity
|
||||
Array->Size = 0;
|
||||
Array->Capacity = INITIAL_ARRAY_CAPACITY;
|
||||
|
||||
//
|
||||
// Allocate memory
|
||||
Array->Data = (UCHAR*)ExAllocatePoolWithTag(PagedPool, Array->Capacity, ARRAY_POOL_TAG);
|
||||
if (Array->Data == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS AppendElementByteArray(IN PBYTE_ARRAY Array, IN PVOID Element)
|
||||
{
|
||||
//
|
||||
// Make sure there is room to expand into
|
||||
if (((Array->Size + 1) * sizeof(UCHAR)) > Array->Capacity)
|
||||
{
|
||||
//
|
||||
// Increase capacity
|
||||
NTSTATUS status = IncreaseCapacityByteArray(Array, sizeof(UCHAR));
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Append the element and increment the size
|
||||
RtlCopyMemory(Array->Data + (Array->Size * sizeof(UCHAR)), Element, sizeof(UCHAR));
|
||||
|
||||
//
|
||||
// Increment size
|
||||
Array->Size += 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS AppendElementsByteArray(IN PBYTE_ARRAY Array, IN PVOID Elements, IN ULONG NumElements)
|
||||
{
|
||||
//
|
||||
// Make sure there is room to expand into
|
||||
if ((Array->Size + NumElements) * sizeof(UCHAR) > Array->Capacity)
|
||||
{
|
||||
//
|
||||
// Increase capacity
|
||||
NTSTATUS status = IncreaseCapacityByteArray(Array, NumElements);
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Append the elements and increase the size
|
||||
RtlCopyMemory(Array->Data + (Array->Size * sizeof(UCHAR)), Elements, NumElements * sizeof(UCHAR));
|
||||
|
||||
//
|
||||
// Increase size
|
||||
Array->Size += NumElements;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS IncreaseCapacityByteArray(IN PBYTE_ARRAY Array, IN ULONG NumElements)
|
||||
{
|
||||
UCHAR* NewData = NULL;
|
||||
|
||||
//
|
||||
// Align new size to the immediate next page boundary
|
||||
Array->Capacity = align_to_page_size((Array->Size + NumElements) * sizeof(UCHAR));
|
||||
|
||||
//
|
||||
// Allocate new data with new capacity
|
||||
NewData = (UCHAR*)ExAllocatePoolWithTag(PagedPool, Array->Capacity, ARRAY_POOL_TAG);
|
||||
if (NewData == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
//
|
||||
// Copy old data over
|
||||
RtlCopyMemory(NewData, Array->Data, Array->Size * sizeof(UCHAR));
|
||||
|
||||
//
|
||||
// Free old data
|
||||
ExFreePoolWithTag(Array->Data, ARRAY_POOL_TAG);
|
||||
|
||||
//
|
||||
// Set data pointer to new allocation
|
||||
Array->Data = NewData;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS GetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Element)
|
||||
{
|
||||
//
|
||||
// Check array bounds
|
||||
if (Index >= Array->Size || (LONG)Index < 0)
|
||||
return STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
|
||||
//
|
||||
// Copy data over
|
||||
RtlCopyMemory(Element, Array->Data + (Index * sizeof(UCHAR)), sizeof(UCHAR));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS GetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Elements, IN ULONG NumElements)
|
||||
{
|
||||
//
|
||||
// Check array bounds
|
||||
if (Index >= Array->Size || (LONG)Index < 0)
|
||||
return STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
|
||||
//
|
||||
// Copy data over
|
||||
RtlCopyMemory(Elements, Array->Data + (Index * sizeof(UCHAR)), NumElements * sizeof(UCHAR));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS SetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Element)
|
||||
{
|
||||
//
|
||||
// Check array bounds
|
||||
if (Index >= Array->Size || (LONG)Index < 0)
|
||||
return STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
|
||||
//
|
||||
// Copy data over
|
||||
RtlCopyMemory(Array->Data + (Index * sizeof(UCHAR)), Element, sizeof(UCHAR));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS SetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Elements, IN ULONG NumElements)
|
||||
{
|
||||
//
|
||||
// Check array bounds
|
||||
if (Index >= Array->Size || (LONG)Index < 0)
|
||||
return STATUS_ARRAY_BOUNDS_EXCEEDED;
|
||||
|
||||
//
|
||||
// Copy data over
|
||||
RtlCopyMemory(Array->Data + (Index * sizeof(UCHAR)), Elements, NumElements * sizeof(UCHAR));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FreeByteArray(IN PBYTE_ARRAY Array)
|
||||
{
|
||||
if (Array->Data == NULL)
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
|
||||
//
|
||||
// Free data
|
||||
ExFreePoolWithTag(Array->Data, ARRAY_POOL_TAG);
|
||||
|
||||
//
|
||||
// Null out everything
|
||||
Array->Data = NULL;
|
||||
Array->Size = 0;
|
||||
Array->Capacity = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ntifs.h>
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
#define INITIAL_ARRAY_CAPACITY PAGE_SIZE
|
||||
#define ARRAY_POOL_TAG 'arrA'
|
||||
|
||||
typedef struct _BYTE_ARRAY
|
||||
{
|
||||
UCHAR* Data; //> array of data we're storing
|
||||
ULONG_PTR Size; //> slots used so far
|
||||
ULONG_PTR Capacity; //> total available memory
|
||||
} BYTE_ARRAY, *PBYTE_ARRAY;
|
||||
|
||||
NTSTATUS InitByteArray(IN OUT PBYTE_ARRAY Array);
|
||||
|
||||
NTSTATUS AppendElementByteArray(IN PBYTE_ARRAY Array, IN PVOID Element);
|
||||
|
||||
NTSTATUS AppendElementsByteArray(IN PBYTE_ARRAY Array, IN PVOID Elements, IN ULONG NumElements);
|
||||
|
||||
NTSTATUS GetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Element);
|
||||
|
||||
NTSTATUS GetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, OUT PVOID Elements, IN ULONG NumElements);
|
||||
|
||||
NTSTATUS SetElementByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Element);
|
||||
|
||||
NTSTATUS SetElementsByteArray(IN PBYTE_ARRAY Array, IN ULONG Index, IN PVOID Elements, IN ULONG NumElements);
|
||||
|
||||
NTSTATUS FreeByteArray(IN PBYTE_ARRAY Array);
|
||||
|
||||
EXTERN_C_END
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
//
|
||||
// FDO (bus device) context data
|
||||
//
|
||||
typedef struct _FDO_DEVICE_DATA
|
||||
{
|
||||
//
|
||||
// Counter of interface references
|
||||
//
|
||||
LONG InterfaceReferenceCounter;
|
||||
|
||||
//
|
||||
// Next SessionId to assign to a file handle
|
||||
//
|
||||
LONG NextSessionId;
|
||||
|
||||
//
|
||||
// Periodic timer sweeping up orphaned requests
|
||||
//
|
||||
WDFTIMER PendingPluginRequestsCleanupTimer;
|
||||
|
||||
} FDO_DEVICE_DATA, *PFDO_DEVICE_DATA;
|
||||
|
||||
#define FDO_FIRST_SESSION_ID 100
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DEVICE_DATA, FdoGetData)
|
||||
|
||||
//
|
||||
// Context data associated with file objects created by user mode applications
|
||||
//
|
||||
typedef struct _FDO_FILE_DATA
|
||||
{
|
||||
//
|
||||
// SessionId associated with file handle. Used to map file handles to emulated gamepad devices
|
||||
//
|
||||
LONG SessionId;
|
||||
|
||||
} FDO_FILE_DATA, *PFDO_FILE_DATA;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_FILE_DATA, FileObjectGetData)
|
||||
|
||||
//
|
||||
// Context data for plugin requests
|
||||
//
|
||||
typedef struct _FDO_PLUGIN_REQUEST_DATA
|
||||
{
|
||||
//
|
||||
// Unique serial number of the device on the bus
|
||||
//
|
||||
ULONG Serial;
|
||||
|
||||
//
|
||||
// High resolution timestamp taken when this request got moved to pending state
|
||||
//
|
||||
LARGE_INTEGER Timestamp;
|
||||
|
||||
//
|
||||
// Performance counter system frequency taken upon fetching timestamp
|
||||
//
|
||||
LARGE_INTEGER Frequency;
|
||||
|
||||
} FDO_PLUGIN_REQUEST_DATA, *PFDO_PLUGIN_REQUEST_DATA;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_PLUGIN_REQUEST_DATA, PluginRequestGetData)
|
||||
|
||||
@@ -24,13 +24,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <ntifs.h>
|
||||
#include "Ds4Pdo.hpp"
|
||||
#include "trace.h"
|
||||
#include "Ds4Pdo.tmh"
|
||||
#define NTSTRSAFE_LIB
|
||||
#include <ntstrsafe.h>
|
||||
#include <hidclass.h>
|
||||
|
||||
|
||||
|
||||
PCWSTR ViGEm::Bus::Targets::EmulationTargetDS4::_deviceDescription = L"Virtual DualShock 4 Controller";
|
||||
@@ -39,8 +38,19 @@ ViGEm::Bus::Targets::EmulationTargetDS4::EmulationTargetDS4(ULONG Serial, LONG S
|
||||
USHORT ProductId) : EmulationTargetPDO(
|
||||
Serial, SessionId, VendorId, ProductId)
|
||||
{
|
||||
_TargetType = DualShock4Wired;
|
||||
_UsbConfigurationDescriptionSize = DS4_DESCRIPTOR_SIZE;
|
||||
this->_TargetType = DualShock4Wired;
|
||||
this->_UsbConfigurationDescriptionSize = DS4_DESCRIPTOR_SIZE;
|
||||
|
||||
//
|
||||
// Set PNP Capabilities
|
||||
//
|
||||
this->_PnpCapabilities.SurpriseRemovalOK = WdfTrue;
|
||||
|
||||
//
|
||||
// Set Power Capabilities
|
||||
//
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
|
||||
this->_PowerCapabilities.WakeFromD0 = WdfTrue;
|
||||
}
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_INIT DeviceInit,
|
||||
@@ -131,34 +141,6 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareDevice(PWDFDEVICE_IN
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::PdoPrepareHardware()
|
||||
{
|
||||
WDF_QUERY_INTERFACE_CONFIG ifaceCfg;
|
||||
INTERFACE devinterfaceHid;
|
||||
|
||||
devinterfaceHid.Size = sizeof(INTERFACE);
|
||||
devinterfaceHid.Version = 1;
|
||||
devinterfaceHid.Context = static_cast<PVOID>(this->_PdoDevice);
|
||||
|
||||
devinterfaceHid.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
|
||||
devinterfaceHid.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
|
||||
|
||||
// Expose GUID_DEVINTERFACE_HID so HIDUSB can initialize
|
||||
WDF_QUERY_INTERFACE_CONFIG_INIT(
|
||||
&ifaceCfg,
|
||||
(PINTERFACE)&devinterfaceHid,
|
||||
&GUID_DEVINTERFACE_HID,
|
||||
NULL
|
||||
);
|
||||
|
||||
NTSTATUS status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_DS4,
|
||||
"WdfDeviceAddQueryInterface failed with status %!STATUS!",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Set default HID input report (everything zero`d)
|
||||
UCHAR DefaultHidReport[DS4_REPORT_SIZE] =
|
||||
{
|
||||
@@ -1127,6 +1109,41 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetDS4::SubmitReportImpl(PVOID NewRepo
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID ViGEm::Bus::Targets::EmulationTargetDS4::ReverseByteArray(PUCHAR Array, INT Length)
|
||||
{
|
||||
const auto s = static_cast<PUCHAR>(ExAllocatePoolWithTag(
|
||||
NonPagedPool,
|
||||
sizeof(UCHAR) * Length,
|
||||
'U4SD'
|
||||
));
|
||||
INT c, d;
|
||||
|
||||
if (s == nullptr)
|
||||
return;
|
||||
|
||||
for (c = Length - 1, d = 0; c >= 0; c--, d++)
|
||||
*(s + d) = *(Array + c);
|
||||
|
||||
for (c = 0; c < Length; c++)
|
||||
*(Array + c) = *(s + c);
|
||||
|
||||
ExFreePoolWithTag(s, 'U4SD');
|
||||
}
|
||||
|
||||
VOID ViGEm::Bus::Targets::EmulationTargetDS4::GenerateRandomMacAddress(PMAC_ADDRESS Address)
|
||||
{
|
||||
// Vendor "C0:13:37"
|
||||
Address->Vendor0 = 0xC0;
|
||||
Address->Vendor1 = 0x13;
|
||||
Address->Vendor2 = 0x37;
|
||||
|
||||
ULONG seed = KeQueryPerformanceCounter(NULL).LowPart;
|
||||
|
||||
Address->Nic0 = RtlRandomEx(&seed) % 0xFF;
|
||||
Address->Nic1 = RtlRandomEx(&seed) % 0xFF;
|
||||
Address->Nic2 = RtlRandomEx(&seed) % 0xFF;
|
||||
}
|
||||
|
||||
VOID ViGEm::Bus::Targets::EmulationTargetDS4::PendingUsbRequestsTimerFunc(
|
||||
_In_ WDFTIMER Timer
|
||||
)
|
||||
|
||||
@@ -29,11 +29,22 @@
|
||||
#include "EmulationTargetPDO.hpp"
|
||||
#include <ViGEm/km/BusShared.h>
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
namespace ViGEm::Bus::Targets
|
||||
{
|
||||
//
|
||||
// Represents a MAC address.
|
||||
//
|
||||
typedef struct _MAC_ADDRESS
|
||||
{
|
||||
UCHAR Vendor0;
|
||||
UCHAR Vendor1;
|
||||
UCHAR Vendor2;
|
||||
UCHAR Nic0;
|
||||
UCHAR Nic1;
|
||||
UCHAR Nic2;
|
||||
} MAC_ADDRESS, * PMAC_ADDRESS;
|
||||
|
||||
constexpr unsigned char hid_get_report_id(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST* pReq)
|
||||
{
|
||||
return pReq->Value & 0xFF;
|
||||
@@ -48,7 +59,6 @@ namespace ViGEm::Bus::Targets
|
||||
{
|
||||
public:
|
||||
EmulationTargetDS4(ULONG Serial, LONG SessionId, USHORT VendorId = 0x054C, USHORT ProductId = 0x05C4);
|
||||
~EmulationTargetDS4() = default;
|
||||
|
||||
NTSTATUS PdoPrepareDevice(PWDFDEVICE_INIT DeviceInit,
|
||||
PUNICODE_STRING DeviceId,
|
||||
@@ -65,14 +75,28 @@ namespace ViGEm::Bus::Targets
|
||||
NTSTATUS SelectConfiguration(PURB Urb) override;
|
||||
|
||||
void AbortPipe() override;
|
||||
|
||||
NTSTATUS UsbClassInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbGetDescriptorFromInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbSelectInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbGetStringDescriptorType(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request) override;
|
||||
|
||||
NTSTATUS UsbControlTransfer(PURB Urb) override;
|
||||
|
||||
NTSTATUS SubmitReportImpl(PVOID NewReport) override;
|
||||
|
||||
private:
|
||||
static EVT_WDF_TIMER PendingUsbRequestsTimerFunc;
|
||||
|
||||
static VOID ReverseByteArray(PUCHAR Array, INT Length);
|
||||
|
||||
static VOID GenerateRandomMacAddress(PMAC_ADDRESS Address);
|
||||
|
||||
static PCWSTR _deviceDescription;
|
||||
|
||||
static const int HID_REQUEST_GET_REPORT = 0x01;
|
||||
@@ -123,8 +147,6 @@ namespace ViGEm::Bus::Targets
|
||||
//
|
||||
// Default MAC address of the host (not used)
|
||||
//
|
||||
MAC_ADDRESS _HostMacAddress;
|
||||
|
||||
static EVT_WDF_TIMER PendingUsbRequestsTimerFunc;
|
||||
MAC_ADDRESS _HostMacAddress;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <ntstrsafe.h>
|
||||
#include <usbioctl.h>
|
||||
#include <usbiodef.h>
|
||||
#include <ViGEmBusDriver.h>
|
||||
|
||||
|
||||
PCWSTR ViGEm::Bus::Core::EmulationTargetPDO::_deviceLocation = L"Virtual Gamepad Emulation Bus";
|
||||
@@ -40,8 +39,6 @@ PCWSTR ViGEm::Bus::Core::EmulationTargetPDO::_deviceLocation = L"Virtual Gamepad
|
||||
NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentDevice, PWDFDEVICE_INIT DeviceInit)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
|
||||
WDF_DEVICE_POWER_CAPABILITIES powerCaps;
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
|
||||
WDF_OBJECT_ATTRIBUTES pdoAttributes;
|
||||
WDF_IO_QUEUE_CONFIG defaultPdoQueueConfig;
|
||||
@@ -70,32 +67,6 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
|
||||
do
|
||||
{
|
||||
#pragma region Enter RAW device mode
|
||||
|
||||
status = WdfPdoInitAssignRawDevice(DeviceInit, &GUID_DEVCLASS_VIGEM_RAWPDO);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_BUSPDO,
|
||||
"WdfPdoInitAssignRawDevice failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
WdfDeviceInitSetCharacteristics(DeviceInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE);
|
||||
|
||||
status = WdfDeviceInitAssignSDDLString(DeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_BUSPDO,
|
||||
"WdfDeviceInitAssignSDDLString failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Prepare PDO
|
||||
|
||||
status = this->PdoPrepareDevice(DeviceInit, &deviceId, &deviceDescription);
|
||||
@@ -303,35 +274,24 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::PdoCreateDevice(WDFDEVICE ParentD
|
||||
|
||||
#pragma region PNP capabilities
|
||||
|
||||
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
|
||||
//
|
||||
// Other capabilities initialized in derived class
|
||||
//
|
||||
|
||||
pnpCaps.Removable = WdfTrue;
|
||||
pnpCaps.EjectSupported = WdfTrue;
|
||||
pnpCaps.SurpriseRemovalOK = WdfTrue;
|
||||
this->_PnpCapabilities.Address = this->_SerialNo;
|
||||
this->_PnpCapabilities.UINumber = this->_SerialNo;
|
||||
|
||||
pnpCaps.Address = this->_SerialNo;
|
||||
pnpCaps.UINumber = this->_SerialNo;
|
||||
|
||||
WdfDeviceSetPnpCapabilities(this->_PdoDevice, &pnpCaps);
|
||||
WdfDeviceSetPnpCapabilities(this->_PdoDevice, &this->_PnpCapabilities);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Power capabilities
|
||||
|
||||
WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);
|
||||
//
|
||||
// Capabilities initialized in derived class
|
||||
//
|
||||
|
||||
powerCaps.DeviceD1 = WdfTrue;
|
||||
powerCaps.WakeFromD1 = WdfTrue;
|
||||
powerCaps.DeviceWake = PowerDeviceD1;
|
||||
|
||||
powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0;
|
||||
powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
|
||||
powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
|
||||
powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
|
||||
powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
|
||||
powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
|
||||
|
||||
WdfDeviceSetPowerCapabilities(this->_PdoDevice, &powerCaps);
|
||||
WdfDeviceSetPowerCapabilities(this->_PdoDevice, &this->_PowerCapabilities);
|
||||
|
||||
#pragma endregion
|
||||
} while (FALSE);
|
||||
@@ -354,6 +314,34 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::EvtDeviceContextCleanup(
|
||||
//
|
||||
WdfIoQueuePurgeSynchronously(ctx->Target->_PendingPlugInRequests);
|
||||
WdfObjectDelete(ctx->Target->_PendingPlugInRequests);
|
||||
|
||||
//
|
||||
// Wait for thread to finish, if active
|
||||
//
|
||||
if (ctx->Target->_PluginRequestCompletionWorkerThreadHandle)
|
||||
{
|
||||
NTSTATUS status = KeWaitForSingleObject(
|
||||
&ctx->Target->_PluginRequestCompletionWorkerThreadHandle,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
ZwClose(ctx->Target->_PluginRequestCompletionWorkerThreadHandle);
|
||||
ctx->Target->_PluginRequestCompletionWorkerThreadHandle = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"KeWaitForSingleObject failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PDO device object getting disposed, free context object
|
||||
@@ -392,13 +380,34 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueuePlugin(WDFREQUEST Request)
|
||||
NTSTATUS status;
|
||||
|
||||
if (!this->IsOwnerProcess())
|
||||
{
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!this->_PendingPlugInRequests)
|
||||
{
|
||||
return STATUS_INVALID_DEVICE_STATE;
|
||||
|
||||
if (this->_PluginRequestCompletionWorkerThreadHandle)
|
||||
{
|
||||
status = KeWaitForSingleObject(
|
||||
&this->_PluginRequestCompletionWorkerThreadHandle,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
ZwClose(this->_PluginRequestCompletionWorkerThreadHandle);
|
||||
this->_PluginRequestCompletionWorkerThreadHandle = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"KeWaitForSingleObject failed with status %!STATUS!",
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
status = WdfRequestForwardToIoQueue(Request, this->_PendingPlugInRequests);
|
||||
@@ -419,7 +428,7 @@ NTSTATUS ViGEm::Bus::Core::EmulationTargetPDO::EnqueuePlugin(WDFREQUEST Request)
|
||||
InitializeObjectAttributes(&threadOb, NULL,
|
||||
OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
|
||||
status = PsCreateSystemThread(&_PluginRequestCompletionWorkerThreadHandle,
|
||||
status = PsCreateSystemThread(&this->_PluginRequestCompletionWorkerThreadHandle,
|
||||
static_cast<ACCESS_MASK>(0L),
|
||||
&threadOb,
|
||||
nullptr,
|
||||
@@ -543,11 +552,11 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::PluginRequestCompletionWorkerRoutine(
|
||||
|
||||
WDFREQUEST pluginRequest;
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = WDF_REL_TIMEOUT_IN_SEC(1);;
|
||||
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(
|
||||
@@ -566,8 +575,8 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::PluginRequestCompletionWorkerRoutine(
|
||||
if (!NT_SUCCESS(WdfIoQueueRetrieveNextRequest(ctx->_PendingPlugInRequests, &pluginRequest)))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"No pending plugin request available"
|
||||
TRACE_BUSPDO,
|
||||
"No pending plugin request available"
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -575,10 +584,10 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::PluginRequestCompletionWorkerRoutine(
|
||||
if (status == STATUS_TIMEOUT)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_BUSPDO,
|
||||
"Plugin request timed out, completing with error"
|
||||
TRACE_BUSPDO,
|
||||
"Plugin request timed out, completing with error"
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// We haven't hit a path where the event gets signaled, report error
|
||||
//
|
||||
@@ -589,19 +598,59 @@ VOID ViGEm::Bus::Core::EmulationTargetPDO::PluginRequestCompletionWorkerRoutine(
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_INFORMATION,
|
||||
TRACE_BUSPDO,
|
||||
"Plugin request completed successfully"
|
||||
TRACE_BUSPDO,
|
||||
"Plugin request completed successfully"
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// Event triggered in time, complete with success
|
||||
//
|
||||
WdfRequestComplete(pluginRequest, STATUS_SUCCESS);
|
||||
break;
|
||||
}
|
||||
} while (FALSE);
|
||||
}
|
||||
while (FALSE);
|
||||
|
||||
ZwClose(ctx->_PluginRequestCompletionWorkerThreadHandle);
|
||||
ctx->_PluginRequestCompletionWorkerThreadHandle = nullptr;
|
||||
KeClearEvent(&ctx->_PdoBootNotificationEvent);
|
||||
(void)PsTerminateSystemThread(0);
|
||||
}
|
||||
|
||||
VOID ViGEm::Bus::Core::EmulationTargetPDO::DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength)
|
||||
{
|
||||
#ifdef DBG
|
||||
|
||||
size_t dumpBufferLength = ((BufferLength * sizeof(CHAR)) * 2) + 1;
|
||||
PSTR dumpBuffer = static_cast<PSTR>(ExAllocatePoolWithTag(
|
||||
NonPagedPoolNx,
|
||||
dumpBufferLength,
|
||||
'1234'
|
||||
));
|
||||
if (dumpBuffer)
|
||||
{
|
||||
|
||||
RtlZeroMemory(dumpBuffer, dumpBufferLength);
|
||||
|
||||
for (ULONG i = 0; i < BufferLength; i++)
|
||||
{
|
||||
sprintf(&dumpBuffer[i * 2], "%02X", static_cast<PUCHAR>(Buffer)[i]);
|
||||
}
|
||||
|
||||
TraceDbg(TRACE_BUSPDO,
|
||||
"%s - Buffer length: %04d, buffer content: %s\n",
|
||||
Prefix,
|
||||
BufferLength,
|
||||
dumpBuffer
|
||||
);
|
||||
|
||||
ExFreePoolWithTag(dumpBuffer, '1234');
|
||||
}
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(Prefix);
|
||||
UNREFERENCED_PARAMETER(Buffer);
|
||||
UNREFERENCED_PARAMETER(BufferLength);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ViGEm::Bus::Core::EmulationTargetPDO::UsbAbortPipe()
|
||||
@@ -664,6 +713,9 @@ _ProductId(ProductId)
|
||||
{
|
||||
this->_OwnerProcessId = current_process_id();
|
||||
KeInitializeEvent(&this->_PdoBootNotificationEvent, NotificationEvent, FALSE);
|
||||
|
||||
WDF_DEVICE_PNP_CAPABILITIES_INIT(&this->_PnpCapabilities);
|
||||
WDF_DEVICE_POWER_CAPABILITIES_INIT(&this->_PowerCapabilities);
|
||||
}
|
||||
|
||||
bool ViGEm::Bus::Core::EmulationTargetPDO::GetPdoBySerial(
|
||||
|
||||
@@ -126,6 +126,8 @@ namespace ViGEm::Bus::Core
|
||||
protected:
|
||||
static const ULONG _maxHardwareIdLength = 0xFF;
|
||||
|
||||
static const int MAX_INSTANCE_ID_LEN = 80;
|
||||
|
||||
static PCWSTR _deviceLocation;
|
||||
|
||||
static BOOLEAN USB_BUSIFFN UsbInterfaceIsDeviceHighSpeed(IN PVOID BusContext);
|
||||
@@ -153,9 +155,7 @@ namespace ViGEm::Bus::Core
|
||||
static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl;
|
||||
|
||||
static VOID PluginRequestCompletionWorkerRoutine(IN PVOID StartContext);
|
||||
|
||||
static const int MAX_INSTANCE_ID_LEN = 80;
|
||||
|
||||
|
||||
virtual VOID GetConfigurationDescriptorType(PUCHAR Buffer, ULONG Length) = 0;
|
||||
|
||||
virtual NTSTATUS SelectConfiguration(PURB Urb) = 0;
|
||||
@@ -163,6 +163,18 @@ namespace ViGEm::Bus::Core
|
||||
virtual void AbortPipe() = 0;
|
||||
|
||||
virtual NTSTATUS SubmitReportImpl(PVOID NewReport) = 0;
|
||||
|
||||
static VOID DumpAsHex(PCSTR Prefix, PVOID Buffer, ULONG BufferLength);
|
||||
|
||||
//
|
||||
// PNP Capabilities may differ from device to device
|
||||
//
|
||||
WDF_DEVICE_PNP_CAPABILITIES _PnpCapabilities;
|
||||
|
||||
//
|
||||
// Power Capabilities may differ from device to device
|
||||
//
|
||||
WDF_DEVICE_POWER_CAPABILITIES _PowerCapabilities;
|
||||
|
||||
//
|
||||
// Unique serial number of the device on the bus
|
||||
@@ -215,7 +227,7 @@ namespace ViGEm::Bus::Core
|
||||
WDFDEVICE _PdoDevice{};
|
||||
|
||||
//
|
||||
// Configuration descriptor size
|
||||
// Configuration descriptor size (populated by derived class)
|
||||
//
|
||||
ULONG _UsbConfigurationDescriptionSize{};
|
||||
|
||||
|
||||
146
sys/Queue.cpp
146
sys/Queue.cpp
@@ -56,15 +56,15 @@ VOID Bus_EvtIoDeviceControl(
|
||||
IN ULONG IoControlCode
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
WDFDEVICE Device;
|
||||
size_t length = 0;
|
||||
PXUSB_SUBMIT_REPORT xusbSubmit = NULL;
|
||||
PXUSB_REQUEST_NOTIFICATION xusbNotify = NULL;
|
||||
PDS4_SUBMIT_REPORT ds4Submit = NULL;
|
||||
PDS4_REQUEST_NOTIFICATION ds4Notify = NULL;
|
||||
PVIGEM_CHECK_VERSION pCheckVersion = NULL;
|
||||
PXUSB_GET_USER_INDEX pXusbGetUserIndex = NULL;
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
WDFDEVICE Device;
|
||||
size_t length = 0;
|
||||
PXUSB_SUBMIT_REPORT xusbSubmit = nullptr;
|
||||
PXUSB_REQUEST_NOTIFICATION xusbNotify = nullptr;
|
||||
PDS4_SUBMIT_REPORT ds4Submit = nullptr;
|
||||
PDS4_REQUEST_NOTIFICATION ds4Notify = nullptr;
|
||||
PVIGEM_CHECK_VERSION pCheckVersion = nullptr;
|
||||
PXUSB_GET_USER_INDEX pXusbGetUserIndex = nullptr;
|
||||
EmulationTargetPDO* pdo;
|
||||
|
||||
Device = WdfIoQueueGetDevice(Queue);
|
||||
@@ -74,7 +74,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
switch (IoControlCode)
|
||||
{
|
||||
#pragma region IOCTL_VIGEM_CHECK_VERSION
|
||||
|
||||
|
||||
case IOCTL_VIGEM_CHECK_VERSION:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_CHECK_VERSION");
|
||||
@@ -82,7 +82,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(VIGEM_CHECK_VERSION),
|
||||
(PVOID*)&pCheckVersion,
|
||||
reinterpret_cast<PVOID*>(&pCheckVersion),
|
||||
&length
|
||||
);
|
||||
|
||||
@@ -95,16 +95,16 @@ VOID Bus_EvtIoDeviceControl(
|
||||
status = (pCheckVersion->Version == VIGEM_COMMON_VERSION) ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
|
||||
|
||||
TraceEvents(TRACE_LEVEL_VERBOSE,
|
||||
TRACE_QUEUE,
|
||||
"Requested version: 0x%04X, compiled version: 0x%04X",
|
||||
pCheckVersion->Version, VIGEM_COMMON_VERSION);
|
||||
TRACE_QUEUE,
|
||||
"Requested version: 0x%04X, compiled version: 0x%04X",
|
||||
pCheckVersion->Version, VIGEM_COMMON_VERSION);
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_VIGEM_PLUGIN_TARGET
|
||||
|
||||
|
||||
case IOCTL_VIGEM_PLUGIN_TARGET:
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_PLUGIN_TARGET");
|
||||
@@ -112,40 +112,40 @@ VOID Bus_EvtIoDeviceControl(
|
||||
status = Bus_PlugInDevice(Device, Request, FALSE, &length);
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_VIGEM_UNPLUG_TARGET
|
||||
|
||||
|
||||
case IOCTL_VIGEM_UNPLUG_TARGET:
|
||||
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_VIGEM_UNPLUG_TARGET");
|
||||
|
||||
status = Bus_UnPlugDevice(Device, Request, FALSE, &length);
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_XUSB_SUBMIT_REPORT
|
||||
|
||||
|
||||
case IOCTL_XUSB_SUBMIT_REPORT:
|
||||
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_XUSB_SUBMIT_REPORT");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(XUSB_SUBMIT_REPORT),
|
||||
(PVOID*)&xusbSubmit,
|
||||
reinterpret_cast<PVOID*>(&xusbSubmit),
|
||||
&length
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -155,8 +155,8 @@ VOID Bus_EvtIoDeviceControl(
|
||||
if (xusbSubmit->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
@@ -169,38 +169,38 @@ VOID Bus_EvtIoDeviceControl(
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_XUSB_REQUEST_NOTIFICATION
|
||||
|
||||
|
||||
case IOCTL_XUSB_REQUEST_NOTIFICATION:
|
||||
|
||||
|
||||
TraceDbg(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,
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
(int)OutputBufferLength, (int)sizeof(XUSB_REQUEST_NOTIFICATION));
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(XUSB_REQUEST_NOTIFICATION)));
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(XUSB_REQUEST_NOTIFICATION),
|
||||
(PVOID*)&xusbNotify,
|
||||
reinterpret_cast<PVOID*>(&xusbNotify),
|
||||
&length
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ VOID Bus_EvtIoDeviceControl(
|
||||
if (xusbNotify->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
@@ -228,28 +228,28 @@ VOID Bus_EvtIoDeviceControl(
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_DS4_SUBMIT_REPORT
|
||||
|
||||
|
||||
case IOCTL_DS4_SUBMIT_REPORT:
|
||||
|
||||
|
||||
TraceDbg(TRACE_QUEUE, "IOCTL_DS4_SUBMIT_REPORT");
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(DS4_SUBMIT_REPORT),
|
||||
(PVOID*)&ds4Submit,
|
||||
reinterpret_cast<PVOID*>(&ds4Submit),
|
||||
&length
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -259,8 +259,8 @@ VOID Bus_EvtIoDeviceControl(
|
||||
if (ds4Submit->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
@@ -273,8 +273,8 @@ VOID Bus_EvtIoDeviceControl(
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_DS4_REQUEST_NOTIFICATION
|
||||
|
||||
@@ -286,25 +286,25 @@ VOID Bus_EvtIoDeviceControl(
|
||||
if (OutputBufferLength < sizeof(DS4_REQUEST_NOTIFICATION))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
(int)OutputBufferLength, (int)sizeof(DS4_REQUEST_NOTIFICATION));
|
||||
TRACE_QUEUE,
|
||||
"Output buffer %d too small, require at least %d",
|
||||
static_cast<int>(OutputBufferLength), static_cast<int>(sizeof(DS4_REQUEST_NOTIFICATION)));
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(DS4_REQUEST_NOTIFICATION),
|
||||
(PVOID*)&ds4Notify,
|
||||
reinterpret_cast<PVOID*>(&ds4Notify),
|
||||
&length
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
TRACE_QUEUE,
|
||||
"WdfRequestRetrieveInputBuffer failed with status %!STATUS!",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -314,8 +314,8 @@ VOID Bus_EvtIoDeviceControl(
|
||||
if (ds4Notify->SerialNo == 0)
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
TRACE_QUEUE,
|
||||
"Invalid serial 0 submitted");
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
@@ -332,15 +332,15 @@ VOID Bus_EvtIoDeviceControl(
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IOCTL_XUSB_GET_USER_INDEX
|
||||
|
||||
|
||||
case IOCTL_XUSB_GET_USER_INDEX:
|
||||
|
||||
TraceDbg(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))
|
||||
{
|
||||
@@ -351,7 +351,7 @@ VOID Bus_EvtIoDeviceControl(
|
||||
status = WdfRequestRetrieveInputBuffer(
|
||||
Request,
|
||||
sizeof(XUSB_GET_USER_INDEX),
|
||||
(PVOID*)&pXusbGetUserIndex,
|
||||
reinterpret_cast<PVOID*>(&pXusbGetUserIndex),
|
||||
&length);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
@@ -379,14 +379,14 @@ VOID Bus_EvtIoDeviceControl(
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
default:
|
||||
|
||||
TraceEvents(TRACE_LEVEL_WARNING,
|
||||
TRACE_QUEUE,
|
||||
"Unknown I/O control code 0x%X", IoControlCode);
|
||||
TRACE_QUEUE,
|
||||
"Unknown I/O control code 0x%X", IoControlCode);
|
||||
|
||||
break; // default status is STATUS_INVALID_PARAMETER
|
||||
}
|
||||
|
||||
BIN
sys/RCa08996
BIN
sys/RCa08996
Binary file not shown.
56
sys/Util.h
56
sys/Util.h
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Returns the current caller process id.
|
||||
//
|
||||
#define CURRENT_PROCESS_ID() ((DWORD)((DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFF))
|
||||
|
||||
#define IS_OWNER(_pdo_) (_pdo_->OwnerProcessId == CURRENT_PROCESS_ID())
|
||||
|
||||
//
|
||||
// Represents a MAC address.
|
||||
//
|
||||
typedef struct _MAC_ADDRESS
|
||||
{
|
||||
UCHAR Vendor0;
|
||||
UCHAR Vendor1;
|
||||
UCHAR Vendor2;
|
||||
UCHAR Nic0;
|
||||
UCHAR Nic1;
|
||||
UCHAR Nic2;
|
||||
} MAC_ADDRESS, *PMAC_ADDRESS;
|
||||
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
VOID ReverseByteArray(PUCHAR Array, INT Length);
|
||||
VOID GenerateRandomMacAddress(PMAC_ADDRESS Address);
|
||||
|
||||
EXTERN_C_END
|
||||
@@ -35,13 +35,8 @@ DriverVer= ;
|
||||
DefaultDestDir = 12
|
||||
ViGEmBus_Device_CoInstaller_CopyFiles = 11
|
||||
|
||||
; ================= Class section =====================
|
||||
|
||||
[SourceDisksNames.amd64]
|
||||
1 = %DiskName%,,,"\x64"
|
||||
|
||||
[SourceDisksNames.x86]
|
||||
1 = %DiskName%,,,"\x86"
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%,,,
|
||||
|
||||
[SourceDisksFiles]
|
||||
ViGEmBus.sys = 1,,
|
||||
|
||||
@@ -89,27 +89,27 @@
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)client\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)client\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)client\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
|
||||
<IncludePath>$(SolutionDir)include;$(SolutionDir)client\include;$(IncludePath)</IncludePath>
|
||||
<Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
|
||||
<OutDir>$(SolutionDir)bin\$(DDKPlatform)\</OutDir>
|
||||
<EnableInf2cat>false</EnableInf2cat>
|
||||
<EnableInf2cat>true</EnableInf2cat>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Inf>
|
||||
@@ -179,24 +179,19 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="ViGEmBus.inf" />
|
||||
<Inf Include="ViGEmBus_SingleArch.inf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(SolutionDir)\Include\ViGEmBusDriver.h" />
|
||||
<ClInclude Include="..\client\include\ViGEm\km\BusShared.h" />
|
||||
<ClInclude Include="busenum.h" />
|
||||
<ClInclude Include="ByteArray.h" />
|
||||
<ClInclude Include="Context.h" />
|
||||
<ClInclude Include="CRTCPP.hpp" />
|
||||
<ClInclude Include="Ds4Pdo.hpp" />
|
||||
<ClInclude Include="EmulationTargetPDO.hpp" />
|
||||
<ClInclude Include="Queue.hpp" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
<ClInclude Include="Util.h" />
|
||||
<ClInclude Include="XusbPdo.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -205,17 +200,12 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="busenum.cpp" />
|
||||
<ClCompile Include="buspdo.cpp" />
|
||||
<ClCompile Include="ByteArray.c" />
|
||||
<ClCompile Include="Driver.cpp" />
|
||||
<ClCompile Include="Ds4Pdo.cpp" />
|
||||
<ClCompile Include="EmulationTargetPDO.cpp" />
|
||||
<ClCompile Include="Queue.cpp" />
|
||||
<ClCompile Include="Util.c" />
|
||||
<ClCompile Include="XusbPdo.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Common">
|
||||
<UniqueIdentifier>{bbf85b1d-5a75-4302-af4e-46627fcf0d78}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Targets">
|
||||
<UniqueIdentifier>{b00da32a-ce46-490d-9e77-95bb90925995}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -31,26 +28,11 @@
|
||||
<Inf Include="ViGEmBus.inf">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
<Inf Include="ViGEmBus_SingleArch.inf">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="busenum.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Context.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ByteArray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SolutionDir)\Include\ViGEmBusDriver.h">
|
||||
<Filter>Header Files\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -77,12 +59,6 @@
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Util.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ByteArray.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XusbPdo.cpp">
|
||||
<Filter>Source Files\Targets</Filter>
|
||||
</ClCompile>
|
||||
@@ -110,7 +86,4 @@
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,100 +0,0 @@
|
||||
; Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
;
|
||||
; MIT License
|
||||
;
|
||||
; Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
;
|
||||
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
; of this software and associated documentation files (the "Software"), to deal
|
||||
; in the Software without restriction, including without limitation the rights
|
||||
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
; copies of the Software, and to permit persons to whom the Software is
|
||||
; furnished to do so, subject to the following conditions:
|
||||
;
|
||||
; The above copyright notice and this permission notice shall be included in all
|
||||
; copies or substantial portions of the Software.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
; SOFTWARE.
|
||||
|
||||
|
||||
[Version]
|
||||
Signature="$WINDOWS NT$"
|
||||
Class=System
|
||||
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}
|
||||
Provider=%ManufacturerName%
|
||||
CatalogFile=ViGEmBus.cat
|
||||
DriverVer= ;
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
ViGEmBus_Device_CoInstaller_CopyFiles = 11
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%,,,
|
||||
|
||||
[SourceDisksFiles]
|
||||
ViGEmBus.sys = 1,,
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1
|
||||
|
||||
;*****************************************
|
||||
; Install Section
|
||||
;*****************************************
|
||||
|
||||
[Manufacturer]
|
||||
%ManufacturerName%=Standard,NTamd64,NTx86
|
||||
|
||||
[Standard.NTamd64]
|
||||
%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Nefarius\ViGEmBus\Gen1
|
||||
|
||||
[Standard.NTx86]
|
||||
%ViGEmBus.DeviceDesc%=ViGEmBus_Device, Nefarius\ViGEmBus\Gen1
|
||||
|
||||
[ViGEmBus_Device.NT]
|
||||
CopyFiles=Drivers_Dir
|
||||
|
||||
[Drivers_Dir]
|
||||
ViGEmBus.sys
|
||||
|
||||
;-------------- Service installation
|
||||
[ViGEmBus_Device.NT.Services]
|
||||
AddService = ViGEmBus,%SPSVCINST_ASSOCSERVICE%, ViGEmBus_Service_Inst
|
||||
|
||||
; -------------- ViGEmBus driver install sections
|
||||
[ViGEmBus_Service_Inst]
|
||||
DisplayName = %ViGEmBus.SVCDESC%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 3 ; SERVICE_DEMAND_START
|
||||
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
|
||||
ServiceBinary = %12%\ViGEmBus.sys
|
||||
|
||||
;
|
||||
;--- ViGEmBus_Device Coinstaller installation ------
|
||||
;
|
||||
|
||||
[ViGEmBus_Device.NT.CoInstallers]
|
||||
AddReg=ViGEmBus_Device_CoInstaller_AddReg
|
||||
CopyFiles=ViGEmBus_Device_CoInstaller_CopyFiles
|
||||
|
||||
[ViGEmBus_Device_CoInstaller_AddReg]
|
||||
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
|
||||
|
||||
[ViGEmBus_Device_CoInstaller_CopyFiles]
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
|
||||
|
||||
[ViGEmBus_Device.NT.Wdf]
|
||||
KmdfService = ViGEmBus, ViGEmBus_wdfsect
|
||||
[ViGEmBus_wdfsect]
|
||||
KmdfLibraryVersion = $KMDFVERSION$
|
||||
|
||||
[Strings]
|
||||
SPSVCINST_ASSOCSERVICE= 0x00000002
|
||||
ManufacturerName="Nefarius Software Solutions e.U."
|
||||
DiskName = "ViGEmBus Installation Disk"
|
||||
ViGEmBus.DeviceDesc = "Virtual Gamepad Emulation Bus"
|
||||
ViGEmBus.SVCDESC = "Virtual Gamepad Emulation Service"
|
||||
109
sys/XusbPdo.cpp
109
sys/XusbPdo.cpp
@@ -29,9 +29,6 @@
|
||||
#include "XusbPdo.tmh"
|
||||
#define NTSTRSAFE_LIB
|
||||
#include <ntstrsafe.h>
|
||||
#include <wdmguid.h>
|
||||
|
||||
|
||||
#include "busenum.h"
|
||||
|
||||
|
||||
@@ -41,8 +38,30 @@ ViGEm::Bus::Targets::EmulationTargetXUSB::EmulationTargetXUSB(ULONG Serial, LONG
|
||||
USHORT ProductId) : EmulationTargetPDO(
|
||||
Serial, SessionId, VendorId, ProductId)
|
||||
{
|
||||
_TargetType = Xbox360Wired;
|
||||
_UsbConfigurationDescriptionSize = XUSB_DESCRIPTOR_SIZE;
|
||||
this->_TargetType = Xbox360Wired;
|
||||
this->_UsbConfigurationDescriptionSize = XUSB_DESCRIPTOR_SIZE;
|
||||
|
||||
//
|
||||
// Set PNP Capabilities
|
||||
//
|
||||
this->_PnpCapabilities.Removable = WdfTrue;
|
||||
this->_PnpCapabilities.SurpriseRemovalOK = WdfTrue;
|
||||
this->_PnpCapabilities.UniqueID = WdfTrue;
|
||||
|
||||
//
|
||||
// Set Power Capabilities
|
||||
//
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD2;
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD2;
|
||||
this->_PowerCapabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
|
||||
this->_PowerCapabilities.DeviceD1 = WdfTrue;
|
||||
this->_PowerCapabilities.DeviceD2 = WdfTrue;
|
||||
this->_PowerCapabilities.WakeFromD0 = WdfTrue;
|
||||
this->_PowerCapabilities.WakeFromD1 = WdfTrue;
|
||||
this->_PowerCapabilities.WakeFromD2 = WdfTrue;
|
||||
}
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_INIT DeviceInit, PUNICODE_STRING DeviceId,
|
||||
@@ -132,87 +151,13 @@ NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareDevice(PWDFDEVICE_I
|
||||
|
||||
NTSTATUS ViGEm::Bus::Targets::EmulationTargetXUSB::PdoPrepareHardware()
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDF_QUERY_INTERFACE_CONFIG ifaceCfg;
|
||||
|
||||
INTERFACE dummyIface;
|
||||
|
||||
dummyIface.Size = sizeof(INTERFACE);
|
||||
dummyIface.Version = 1;
|
||||
dummyIface.Context = static_cast<PVOID>(this->_PdoDevice);
|
||||
|
||||
dummyIface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
|
||||
dummyIface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
|
||||
|
||||
/* XUSB.sys will query for the following three "dummy" interfaces
|
||||
* BUT WONT USE IT so we just expose them to satisfy initialization. (TODO: Check if still valid!)
|
||||
*/
|
||||
|
||||
// Dummy PNP_LOCATION
|
||||
|
||||
WDF_QUERY_INTERFACE_CONFIG_INIT(
|
||||
&ifaceCfg,
|
||||
static_cast<PINTERFACE>(&dummyIface),
|
||||
&GUID_PNP_LOCATION_INTERFACE,
|
||||
nullptr
|
||||
);
|
||||
|
||||
NTSTATUS status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_XUSB,
|
||||
"Couldn't register PNP_LOCATION dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)",
|
||||
&GUID_PNP_LOCATION_INTERFACE,
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Dummy D3COLD_SUPPORT
|
||||
|
||||
WDF_QUERY_INTERFACE_CONFIG_INIT(
|
||||
&ifaceCfg,
|
||||
static_cast<PINTERFACE>(&dummyIface),
|
||||
&GUID_D3COLD_SUPPORT_INTERFACE,
|
||||
nullptr
|
||||
);
|
||||
|
||||
status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_XUSB,
|
||||
"Couldn't register D3COLD_SUPPORT dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)",
|
||||
&GUID_D3COLD_SUPPORT_INTERFACE,
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Dummy REENUMERATE_SELF_INTERFACE_STANDARD
|
||||
|
||||
WDF_QUERY_INTERFACE_CONFIG_INIT(
|
||||
&ifaceCfg,
|
||||
static_cast<PINTERFACE>(&dummyIface),
|
||||
&GUID_REENUMERATE_SELF_INTERFACE_STANDARD,
|
||||
nullptr
|
||||
);
|
||||
|
||||
status = WdfDeviceAddQueryInterface(this->_PdoDevice, &ifaceCfg);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
TraceEvents(TRACE_LEVEL_ERROR,
|
||||
TRACE_XUSB,
|
||||
"Couldn't register REENUM_SELF_STD dummy interface %!GUID! (WdfDeviceAddQueryInterface failed with status %!STATUS!)",
|
||||
&GUID_REENUMERATE_SELF_INTERFACE_STANDARD,
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Expose USB_BUS_INTERFACE_USBDI_GUID
|
||||
//
|
||||
|
||||
// This interface actually IS used
|
||||
USB_BUS_INTERFACE_USBDI_V1 xusbInterface;
|
||||
|
||||
xusbInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V1);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
namespace ViGEm::Bus::Targets
|
||||
{
|
||||
constexpr auto XUSB_POOL_TAG = 'EGiV';
|
||||
constexpr auto XUSB_POOL_TAG = 'XUiV';
|
||||
|
||||
typedef struct _XUSB_INTERRUPT_IN_PACKET
|
||||
{
|
||||
@@ -55,7 +55,6 @@ namespace ViGEm::Bus::Targets
|
||||
{
|
||||
public:
|
||||
EmulationTargetXUSB(ULONG Serial, LONG SessionId, USHORT VendorId = 0x045E, USHORT ProductId = 0x028E);
|
||||
~EmulationTargetXUSB() = default;
|
||||
|
||||
NTSTATUS PdoPrepareDevice(PWDFDEVICE_INIT DeviceInit,
|
||||
PUNICODE_STRING DeviceId,
|
||||
@@ -74,14 +73,21 @@ namespace ViGEm::Bus::Targets
|
||||
void AbortPipe() override;
|
||||
|
||||
NTSTATUS UsbClassInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbGetDescriptorFromInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbSelectInterface(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbGetStringDescriptorType(PURB Urb) override;
|
||||
|
||||
NTSTATUS UsbBulkOrInterruptTransfer(_URB_BULK_OR_INTERRUPT_TRANSFER* pTransfer, WDFREQUEST Request) override;
|
||||
|
||||
NTSTATUS UsbControlTransfer(PURB Urb) override;
|
||||
|
||||
NTSTATUS SubmitReportImpl(PVOID NewReport) override;
|
||||
|
||||
NTSTATUS GetUserIndex(PULONG UserIndex) const;
|
||||
|
||||
private:
|
||||
static PCWSTR _deviceDescription;
|
||||
|
||||
|
||||
@@ -32,34 +32,52 @@
|
||||
#include <wdf.h>
|
||||
#define NTSTRSAFE_LIB
|
||||
#include <ntstrsafe.h>
|
||||
#include <ntintsafe.h>
|
||||
#include <initguid.h>
|
||||
#include "ViGEmBusDriver.h"
|
||||
#include <ViGEm/km/BusShared.h>
|
||||
#include "Queue.hpp"
|
||||
#include <usb.h>
|
||||
#include <usbbusif.h>
|
||||
#include "Context.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
|
||||
#pragma region Macros
|
||||
|
||||
#define HID_LANGUAGE_ID_LENGTH 0x04
|
||||
|
||||
|
||||
|
||||
#define VIGEM_POOL_TAG 0x45476956 // "EGiV"
|
||||
#define DRIVERNAME "ViGEm: "
|
||||
|
||||
#define ORC_PC_FREQUENCY_DIVIDER 1000
|
||||
#define ORC_TIMER_START_DELAY 500 // ms
|
||||
#define ORC_TIMER_PERIODIC_DUE_TIME 500 // ms
|
||||
#define ORC_REQUEST_MAX_AGE 500 // ms
|
||||
|
||||
#pragma endregion
|
||||
|
||||
//
|
||||
// FDO (bus device) context data
|
||||
//
|
||||
typedef struct _FDO_DEVICE_DATA
|
||||
{
|
||||
//
|
||||
// Counter of interface references
|
||||
//
|
||||
LONG InterfaceReferenceCounter;
|
||||
|
||||
//
|
||||
// Next SessionId to assign to a file handle
|
||||
//
|
||||
LONG NextSessionId;
|
||||
|
||||
} FDO_DEVICE_DATA, * PFDO_DEVICE_DATA;
|
||||
|
||||
#define FDO_FIRST_SESSION_ID 100
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_DEVICE_DATA, FdoGetData)
|
||||
|
||||
//
|
||||
// Context data associated with file objects created by user mode applications
|
||||
//
|
||||
typedef struct _FDO_FILE_DATA
|
||||
{
|
||||
//
|
||||
// SessionId associated with file handle. Used to map file handles to emulated gamepad devices
|
||||
//
|
||||
LONG SessionId;
|
||||
|
||||
} FDO_FILE_DATA, * PFDO_FILE_DATA;
|
||||
|
||||
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_FILE_DATA, FileObjectGetData)
|
||||
|
||||
|
||||
EXTERN_C_START
|
||||
@@ -78,10 +96,6 @@ EVT_WDF_CHILD_LIST_CREATE_DEVICE Bus_EvtDeviceListCreatePdo;
|
||||
|
||||
EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE Bus_EvtChildListIdentificationDescriptionCompare;
|
||||
|
||||
EVT_WDF_DEVICE_PREPARE_HARDWARE Pdo_EvtDevicePrepareHardware;
|
||||
|
||||
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Pdo_EvtIoInternalDeviceControl;
|
||||
|
||||
EVT_WDF_OBJECT_CONTEXT_CLEANUP Bus_EvtDriverContextCleanup;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
62
sys/util.c
62
sys/util.c
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Virtual Gamepad Emulation Framework - Windows kernel-mode bus driver
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2016-2020 Nefarius Software Solutions e.U. and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <ntifs.h>
|
||||
#include "busenum.h"
|
||||
#include "util.tmh"
|
||||
|
||||
|
||||
VOID ReverseByteArray(PUCHAR Array, INT Length)
|
||||
{
|
||||
PUCHAR s = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, sizeof(UCHAR) * Length, VIGEM_POOL_TAG);
|
||||
INT c, d;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
for (c = Length - 1, d = 0; c >= 0; c--, d++)
|
||||
*(s + d) = *(Array + c);
|
||||
|
||||
for (c = 0; c < Length; c++)
|
||||
*(Array + c) = *(s + c);
|
||||
|
||||
ExFreePoolWithTag(s, VIGEM_POOL_TAG);
|
||||
}
|
||||
|
||||
VOID GenerateRandomMacAddress(PMAC_ADDRESS Address)
|
||||
{
|
||||
// Vendor "C0:13:37"
|
||||
Address->Vendor0 = 0xC0;
|
||||
Address->Vendor1 = 0x13;
|
||||
Address->Vendor2 = 0x37;
|
||||
|
||||
ULONG seed = KeQueryPerformanceCounter(NULL).LowPart;
|
||||
|
||||
Address->Nic0 = RtlRandomEx(&seed) % 0xFF;
|
||||
Address->Nic1 = RtlRandomEx(&seed) % 0xFF;
|
||||
Address->Nic2 = RtlRandomEx(&seed) % 0xFF;
|
||||
}
|
||||
Reference in New Issue
Block a user